package cn.jwcat.service.impl;

import cn.jwcat.dealEntity.UserDto;
import cn.jwcat.entity.*;
import cn.jwcat.mapper.UserMapper;
import cn.jwcat.service.IClaimService;
import cn.jwcat.service.IRoomService;
import cn.jwcat.service.IUserService;
import cn.jwcat.utils.MD5;
import cn.jwcat.utils.otherUtils;
import cn.jwcat.utils.result.Result;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 用户 服务实现类
 */
@Transactional
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
	@Resource
	IClaimService claimService;

	@Resource
	IRoomService roomService;

	public static MPJLambdaWrapper<User> getBaseSql(Integer staffId) {
		MPJLambdaWrapper<User> lambdaWrapper = new MPJLambdaWrapper<>();
		return lambdaWrapper
			.selectAll(User.class)
			.select(Room::getName, Room::getDisinfection)
			.select(Area::getAreaName)
			.leftJoin(Room.class, Room::getRoomId, User::getRoomId)
			.leftJoin(Area.class, Area::getAreaId, Room::getAreaId)
			.leftJoin(StaffArea.class, StaffArea::getAreaId, Area::getAreaId)
			.leftJoin(Staff.class, Staff::getStaffId, StaffArea::getStaffId)
			.eq(Staff::getStaffId, staffId)
			.orderByDesc(User::getEnterTime);
	}

	@Override
	public List<UserDto> getUserInfoList(Integer staffId) {
		MPJLambdaWrapper<User> baseSql = getBaseSql(staffId);
		baseSql
			.eq(User::getStatus, true);
		return this.getBaseMapper().selectJoinList(UserDto.class, baseSql);
	}

	@Override
	public List<UserDto> queryUser(Integer staffId, String uname) {
		System.out.println(uname);
		MPJLambdaWrapper<User> baseSql = getBaseSql(staffId);
		baseSql
			.like(User::getUname, uname)
			.eq(User::getStatus, true);
		return this.getBaseMapper().selectJoinList(UserDto.class, baseSql);
	}

	@Override
	public boolean deleteUserById(Integer userId, Integer staffId) {
		// 修改患者居住房间的状态
		MPJLambdaWrapper<Room> baseWrapper = RoomServiceImpl.baseWrapper(staffId);
		baseWrapper.eq(User::getUserId, userId);
		Room room = roomService.getBaseMapper().selectOne(baseWrapper);
		if (room == null) return false;
		room.setStatus(false);
		int i = roomService.getBaseMapper().updateById(room);
		// 删除患者的物资申领
		LambdaQueryWrapper<Claim> wrapper = new LambdaQueryWrapper<>();
		System.out.println("userId" + userId);
		wrapper.eq(Claim::getUserId, userId);
		claimService.remove(wrapper);
		// 删除患者用户
		boolean bool = this.removeById(userId);
		return bool && i == 1;
	}

	@Override
	public Result updateUser(User user) {
		System.out.println("user实现类" + user);
		if (!goPut(user.getUserId(), user.getRoomId()))
			return Result.error().message(user.getRoomId() + "号房间有人居住，请重新选择。");
		if (findRoomOnAreaByTrue(user.getRoomId()))
			return Result.error().message("修改失败！" + user.getRoomId() + "号房间未在开放的区域内。");
		boolean update = this.updateById(user);
		if (update) return Result.success(user.getUname() + "数据更新成功");
		return Result.error().message(user.getUname() + "数据更新失败");
	}

	@Override
	public Result postUser(User user) {
		System.out.println(user);
		if (!goPost(user.getUserId(), user.getRoomId()))
			return Result.error()
				.message(user.getRoomId() + "号房间有人居住，请重新选择。");
		if (findRoomOnAreaByTrue(user.getRoomId()))
			return Result.error()
				.message("添加失败！" + user.getRoomId() + "号房间未在开放的区域内。");
		user.setEnterTime(LocalDateTime.now());
		boolean update = this.save(user);
		if (update) return Result
			.success(user.getUname() + "数据添加成功");
		return Result.error()
			.message(user.getUname() + "数据添加失败");
	}

	@Override
	public Result changePwd(Password password) {
		User user = this.getById(password.getId());
		if (!MD5.getTrue(password.getOldPassword(), user.getPassword())) {
			return Result.error().message("密码修改失败，请检查原始密码");
		}
		String newPassword = MD5.md5MinusSalt(password.getNewPassword());
		LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>();
		wrapper.set(User::getPassword, newPassword).eq(User::getUserId, user.getUserId());
		boolean bool = this.update(wrapper);
		return otherUtils.dealBool(bool);
	}

	@Override
	public Boolean supplement(Integer roomId, Integer uid) {
		return goPost(uid, roomId);
	}

	public boolean goPost(Integer userId, Integer roomId) {
		System.out.println(userId);
		// 查找新房间的居住人
		if (go(userId, roomId)) return false;
		// 改变新房间的启用状态
		Room newRoom = roomService.getById(roomId);
		newRoom.setStatus(true);
		return roomService.updateById(newRoom);
	}

	private boolean go(Integer userId, Integer roomId) {
		MPJLambdaWrapper<User> wrapper = new MPJLambdaWrapper<>();
		wrapper
			.selectAll(User.class)
			.leftJoin(Room.class, Room::getRoomId, User::getRoomId)
			.eq(User::getRoomId, roomId);
		User user = this.getBaseMapper().selectOne(wrapper);
		System.out.println(user);
		return user != null && !userId.equals(user.getUserId());
	}

	public boolean goPut(Integer userId, Integer roomId) {
		System.out.println(userId);
		// 查找新房间的居住人
		if (go(userId, roomId)) return false;
		// 查找旧房间，改变状态
		MPJLambdaWrapper<Room> roomWrapper = new MPJLambdaWrapper<>();
		roomWrapper
			.selectAll(Room.class)
			.rightJoin(User.class, User::getRoomId, Room::getRoomId)
			.eq(User::getUserId, userId);
		Room room = roomService.getBaseMapper().selectOne(roomWrapper);
		room.setStatus(false);
		// 改变新房间的启用状态
		Room newRoom = roomService.getById(roomId);
		newRoom.setStatus(true);
		Room oldRoom = roomService.getBaseMapper().selectOne(roomWrapper);
		oldRoom.setStatus(false);
		boolean saveOldRoom = roomService.updateById(oldRoom);
		boolean saveNewRoom = roomService.updateById(newRoom);
		return saveNewRoom && saveOldRoom;
	}

	// 查找房间是否在已开放的房区内
	public boolean findRoomOnAreaByTrue(Integer roomId) {
		MPJLambdaWrapper<Room> wrapper = new MPJLambdaWrapper<>();
		wrapper
			.selectAll(Room.class)
			.leftJoin(Area.class, Area::getAreaId, Room::getAreaId)
			.eq(Area::getStatus, true)
			.eq(Room::getRoomId, roomId);
		Room room = roomService.getBaseMapper().selectOne(wrapper);
		return room == null;
	}
}
